home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / lib / ruby / 1.8 / sync.rb < prev    next >
Encoding:
Ruby Source  |  2001-06-06  |  6.1 KB  |  312 lines

  1. #
  2. #   sync.rb - 2 phase lock with counter
  3. #       $Release Version: 1.0$
  4. #       $Revision: 1.4 $
  5. #       $Date: 2001/06/06 14:19:33 $
  6. #       by Keiju ISHITSUKA(keiju@ishitsuka.com)
  7. #
  8. # --
  9. #  Sync_m, Synchronizer_m
  10. #  Usage:
  11. #   obj.extend(Sync_m)
  12. #   or
  13. #   class Foo
  14. #    include Sync_m
  15. #    :
  16. #   end
  17. #
  18. #   Sync_m#sync_mode
  19. #   Sync_m#sync_locked?, locked?
  20. #   Sync_m#sync_shared?, shared?
  21. #   Sync_m#sync_exclusive?, sync_exclusive?
  22. #   Sync_m#sync_try_lock, try_lock
  23. #   Sync_m#sync_lock, lock
  24. #   Sync_m#sync_unlock, unlock
  25. #
  26. #   Sync, Synchronicer:
  27. #    include Sync_m
  28. #   Usage:
  29. #   sync = Sync.new
  30. #
  31. #   Sync#mode
  32. #   Sync#locked?
  33. #   Sync#shared?
  34. #   Sync#exclusive?
  35. #   Sync#try_lock(mode) -- mode = :EX, :SH, :UN
  36. #   Sync#lock(mode)     -- mode = :EX, :SH, :UN
  37. #   Sync#unlock
  38. #   Sync#synchronize(mode) {...}
  39. #   
  40. #
  41.  
  42. unless defined? Thread
  43.   fail "Thread not available for this ruby interpreter"
  44. end
  45.  
  46. module Sync_m
  47.   RCS_ID='-$Header: /src/ruby/lib/sync.rb,v 1.4 2001/06/06 14:19:33 keiju Exp $-'
  48.   
  49.   # lock mode
  50.   UN = :UN
  51.   SH = :SH
  52.   EX = :EX
  53.   
  54.   # exceptions
  55.   class Err < StandardError
  56.     def Err.Fail(*opt)
  57.       fail self, sprintf(self::Message, *opt)
  58.     end
  59.     
  60.     class UnknownLocker < Err
  61.       Message = "Thread(%s) not locked."
  62.       def UnknownLocker.Fail(th)
  63.     super(th.inspect)
  64.       end
  65.     end
  66.     
  67.     class LockModeFailer < Err
  68.       Message = "Unknown lock mode(%s)"
  69.       def LockModeFailer.Fail(mode)
  70.     if mode.id2name
  71.       mode = id2name
  72.     end
  73.     super(mode)
  74.       end
  75.     end
  76.   end
  77.   
  78.   def Sync_m.define_aliases(cl)
  79.     cl.module_eval %q{
  80.       alias locked? sync_locked?
  81.       alias shared? sync_shared?
  82.       alias exclusive? sync_exclusive?
  83.       alias lock sync_lock
  84.       alias unlock sync_unlock
  85.       alias try_lock sync_try_lock
  86.       alias synchronize sync_synchronize
  87.     }
  88.   end
  89.   
  90.   def Sync_m.append_features(cl)
  91.     super
  92.     unless cl.instance_of?(Module)
  93.       # do nothing for Modules
  94.       # make aliases and include the proper module.
  95.       define_aliases(cl)
  96.     end
  97.   end
  98.   
  99.   def Sync_m.extend_object(obj)
  100.     super
  101.     obj.sync_extended
  102.   end
  103.  
  104.   def sync_extended
  105.     unless (defined? locked? and
  106.         defined? shared? and
  107.         defined? exclusive? and
  108.         defined? lock and
  109.         defined? unlock and
  110.         defined? try_lock and
  111.         defined? synchronize)
  112.       Sync_m.define_aliases(class<<self;self;end)
  113.     end
  114.     sync_initialize
  115.   end
  116.  
  117.   # accessing
  118.   def sync_locked?
  119.     sync_mode != UN
  120.   end
  121.   
  122.   def sync_shared?
  123.     sync_mode == SH
  124.   end
  125.   
  126.   def sync_exclusive?
  127.     sync_mode == EX
  128.   end
  129.   
  130.   # locking methods.
  131.   def sync_try_lock(mode = EX)
  132.     return unlock if sync_mode == UN
  133.     
  134.     Thread.critical = true
  135.     ret = sync_try_lock_sub(sync_mode)
  136.     Thread.critical = false
  137.     ret
  138.   end
  139.   
  140.   def sync_lock(m = EX)
  141.     return unlock if m == UN
  142.  
  143.     until (Thread.critical = true; sync_try_lock_sub(m))
  144.       if sync_sh_locker[Thread.current]
  145.     sync_upgrade_waiting.push [Thread.current, sync_sh_locker[Thread.current]]
  146.     sync_sh_locker.delete(Thread.current)
  147.       else
  148.     sync_waiting.push Thread.current
  149.       end
  150.       Thread.stop
  151.     end
  152.     Thread.critical = false
  153.     self
  154.   end
  155.   
  156.   def sync_unlock(m = EX)
  157.     Thread.critical = true
  158.     if sync_mode == UN
  159.       Thread.critical = false
  160.       Err::UnknownLocker.Fail(Thread.current)
  161.     end
  162.     
  163.     m = sync_mode if m == EX and sync_mode == SH
  164.     
  165.     runnable = false
  166.     case m
  167.     when UN
  168.       Thread.critical = false
  169.       Err::UnknownLocker.Fail(Thread.current)
  170.       
  171.     when EX
  172.       if sync_ex_locker == Thread.current
  173.     if (self.sync_ex_count = sync_ex_count - 1) == 0
  174.       self.sync_ex_locker = nil
  175.       if sync_sh_locker.include?(Thread.current)
  176.         self.sync_mode = SH
  177.       else
  178.         self.sync_mode = UN
  179.       end
  180.       runnable = true
  181.     end
  182.       else
  183.     Err::UnknownLocker.Fail(Thread.current)
  184.       end
  185.       
  186.     when SH
  187.       if (count = sync_sh_locker[Thread.current]).nil?
  188.     Err::UnknownLocker.Fail(Thread.current)
  189.       else
  190.     if (sync_sh_locker[Thread.current] = count - 1) == 0 
  191.       sync_sh_locker.delete(Thread.current)
  192.       if sync_sh_locker.empty? and sync_ex_count == 0
  193.         self.sync_mode = UN
  194.         runnable = true
  195.       end
  196.     end
  197.       end
  198.     end
  199.     
  200.     if runnable
  201.       if sync_upgrade_waiting.size > 0
  202.     for k, v in sync_upgrade_waiting
  203.       sync_sh_locker[k] = v
  204.     end
  205.     wait = sync_upgrade_waiting
  206.     self.sync_upgrade_waiting = []
  207.     Thread.critical = false
  208.     
  209.     for w, v in wait
  210.       w.run
  211.     end
  212.       else
  213.     wait = sync_waiting
  214.     self.sync_waiting = []
  215.     Thread.critical = false
  216.     for w in wait
  217.       w.run
  218.     end
  219.       end
  220.     end
  221.     
  222.     Thread.critical = false
  223.     self
  224.   end
  225.   
  226.   def sync_synchronize(mode = EX)
  227.     begin
  228.       sync_lock(mode)
  229.       yield
  230.     ensure
  231.       sync_unlock
  232.     end
  233.   end
  234.  
  235.   attr :sync_mode, true
  236.     
  237.   attr :sync_waiting, true
  238.   attr :sync_upgrade_waiting, true
  239.   attr :sync_sh_locker, true
  240.   attr :sync_ex_locker, true
  241.   attr :sync_ex_count, true
  242.     
  243.   private
  244.  
  245.   def sync_initialize
  246.     @sync_mode = UN
  247.     @sync_waiting = []
  248.     @sync_upgrade_waiting = []
  249.     @sync_sh_locker = Hash.new
  250.     @sync_ex_locker = nil
  251.     @sync_ex_count = 0
  252.   end
  253.  
  254.   def initialize(*args)
  255.     sync_initialize
  256.     super
  257.   end
  258.     
  259.   def sync_try_lock_sub(m)
  260.     case m
  261.     when SH
  262.       case sync_mode
  263.       when UN
  264.     self.sync_mode = m
  265.     sync_sh_locker[Thread.current] = 1
  266.     ret = true
  267.       when SH
  268.     count = 0 unless count = sync_sh_locker[Thread.current]
  269.     sync_sh_locker[Thread.current] = count + 1
  270.     ret = true
  271.       when EX
  272.     # in EX mode, lock will upgrade to EX lock
  273.     if sync_ex_locker == Thread.current
  274.       self.sync_ex_count = sync_ex_count + 1
  275.       ret = true
  276.     else
  277.       ret = false
  278.     end
  279.       end
  280.     when EX
  281.       if sync_mode == UN or
  282.     sync_mode == SH && sync_sh_locker.size == 1 && sync_sh_locker.include?(Thread.current) 
  283.     self.sync_mode = m
  284.     self.sync_ex_locker = Thread.current
  285.     self.sync_ex_count = 1
  286.     ret = true
  287.       elsif sync_mode == EX && sync_ex_locker == Thread.current
  288.     self.sync_ex_count = sync_ex_count + 1
  289.     ret = true
  290.       else
  291.     ret = false
  292.       end
  293.     else
  294.       Thread.critical = false
  295.       Err::LockModeFailer.Fail mode
  296.     end
  297.     return ret
  298.   end
  299. end
  300. Synchronizer_m = Sync_m
  301.  
  302. class Sync
  303.   #Sync_m.extend_class self
  304.   include Sync_m
  305.     
  306.   def initialize
  307.     super
  308.   end
  309.     
  310. end
  311. Synchronizer = Sync
  312.